package com.richard.library.port.connect.port;

import android.text.TextUtils;

import com.richard.library.port.connect.enumerate.ErrorCode;
import com.richard.library.port.connect.enumerate.PortType;
import com.richard.library.port.connect.model.PortInfo;
import com.richard.library.port.connect.model.ReturnMessage;
import com.richard.library.port.connect.serialport.SerialPortControl;

import java.io.File;
import java.io.IOException;

/**
 * author：Richard
 * time：2021-09-04 14:58
 * version：v1.0.0
 * description：串口通信
 */
public class SerialPort extends AbsPort {

    private SerialPortControl serialPortControl;

    public SerialPort(PortInfo portInfo) {
        super(portInfo);
        if (portInfo.getPortType() == PortType.Serial && !TextUtils.isEmpty(portInfo.getSerialPath())) {
            try {
                this.mPortInfo.setParIsOK(true);
            } catch (Exception var4) {
                this.mPortInfo.setParIsOK(false);
            }
        } else {
            this.mPortInfo.setParIsOK(false);
        }
    }

    /**
     * 当前端口连接是否可用
     */
    private boolean isPortAvailable() {
        if (!mIsOpen) {
            return false;
        }

        if (serialPortControl == null) {
            return false;
        }

        return serialPortControl.getInputStream() != null && serialPortControl.getOutputStream() != null;
    }

    @Override
    public ReturnMessage openPort() {
        try {
            File file = new File(mPortInfo.getSerialPath());
            if (file.exists()) {
                serialPortControl = new SerialPortControl(file, mPortInfo.getBaudRate(), 0);
                if (serialPortControl.getInputStream() == null || serialPortControl.getOutputStream() == null) {
                    return new ReturnMessage(ErrorCode.OpenPortFailed, "Open Serial port fail !");
                }
            }
            this.mIsOpen = true;
        } catch (IOException var1) {
            return new ReturnMessage(ErrorCode.OpenPortFailed, var1.toString());
        }

        return new ReturnMessage(ErrorCode.OpenPortSuccess, "Open Serial port success !");
    }

    @Override
    public ReturnMessage closePort() {
        try {
            if (this.serialPortControl != null) {
                this.serialPortControl.getOutputStream().flush();
                this.serialPortControl.destroy();
                this.serialPortControl = null;
            }
            this.mIsOpen = false;
        } catch (IOException var1) {
            return new ReturnMessage(ErrorCode.ClosePortFailed, var1.toString());
        }

        return new ReturnMessage(ErrorCode.ClosePortSuccess, "Close serial port success !");
    }

    @Override
    public int getReadAvailable() {
        if (this.isPortAvailable()) {
            try {
                return serialPortControl.getInputStream().available();
            } catch (Exception var6) {
                var6.printStackTrace();
            }
        }
        return 0;
    }

    @Override
    public ReturnMessage write(int data) {
        if (this.isPortAvailable()) {
            try {
                serialPortControl.getOutputStream().write(data);
                serialPortControl.getOutputStream().flush();
            } catch (IOException e) {
                return new ReturnMessage(ErrorCode.WriteDataFailed, e.toString());
            }
            return new ReturnMessage(ErrorCode.WriteDataSuccess, "Send 1 byte .", 1);
        }

        return new ReturnMessage(ErrorCode.WriteDataFailed, "serial port was close !");
    }

    @Override
    public ReturnMessage write(byte[] data) {
        if (this.isPortAvailable()) {
            try {
                serialPortControl.getOutputStream().write(data);
                serialPortControl.getOutputStream().flush();
            } catch (Exception var3) {
                return new ReturnMessage(ErrorCode.WriteDataFailed, var3.toString());
            }

            return new ReturnMessage(ErrorCode.WriteDataSuccess, "Send " + data.length + " bytes .", data.length);
        }

        return new ReturnMessage(ErrorCode.WriteDataFailed, "serial port was close !");
    }

    @Override
    public ReturnMessage write(byte[] data, int offset, int count) {
        if (this.isPortAvailable()) {
            try {
                serialPortControl.getOutputStream().write(data, offset, count);
                serialPortControl.getOutputStream().flush();
            } catch (Exception var5) {
                return new ReturnMessage(ErrorCode.WriteDataFailed, var5.toString());
            }

            return new ReturnMessage(ErrorCode.WriteDataSuccess, "Send " + count + " bytes .", count);
        }

        return new ReturnMessage(ErrorCode.WriteDataFailed, "serial port was close !");
    }

    @Override
    public ReturnMessage read(byte[] buffer, int offset, int count) {
        if (this.isPortAvailable()) {
            int readBytes = -1;
            try {
                if (serialPortControl.getInputStream().available() > 0) {
                    readBytes = serialPortControl.getInputStream().read(buffer, offset, count);
                }

                if (readBytes == -1) {
                    return new ReturnMessage(ErrorCode.ReadDataFailed, "serial port was close !");
                }
            } catch (Exception var6) {
                return new ReturnMessage(ErrorCode.ReadDataFailed, var6.toString());
            }

            return new ReturnMessage(ErrorCode.ReadDataSuccess, "Read " + count + " bytes .", readBytes);
        }

        return new ReturnMessage(ErrorCode.ReadDataFailed, "serial port was close !");
    }

    @Override
    public ReturnMessage read(byte[] buffer) {
        return this.read(buffer, 0, buffer.length);
    }

    @Override
    public int read() {
        if (this.isPortAvailable()) {
            try {
                return serialPortControl.getInputStream().read();
            } catch (Exception var2) {
                return -1;
            }
        }
        return -1;
    }

    @Override
    public boolean portIsOpen() {
        return this.isPortAvailable();
    }
}
